# Eventlet is a concurrent networking library for Python that allows you to change how you run your code, not how you write it.
# 这段摘自官方文档介绍，Evenlet是一个Python的基于携程的网络库，它改变了你代码运行的方式，但是没有改变你怎么写代码
# eventlet 一个是处理和网络相关的，另一个可以通过协程实现并发
# 随eventlet一起部署的Socket.IO服务器可以访问长轮询和WebSocket传输。
import eventlet

# Eventlet提供的monkey_patch()功能可以用等效的异步版本替换标准库中的所有阻塞功能。尽管python-socketio不需要猴子补丁，但其他类库（例如数据库驱动程序）也可能需要它
eventlet.monkey_patch()

import socketio

# 实例化服务器
# cors_allowed_origins 跨域请求
# logger,engineio_logger 日志输出方便查看
sio = socketio.Server(logger=True, engineio_logger=True, cors_allowed_origins='*')

# 方式3：用一个WSGI应用程序封装：创建好app对象后，使用uWSGI、或gunicorn服务器运行此对象。创建好app对象后，使用uWSGI、或gunicorn服务器运行此对象。
app = socketio.WSGIApp(sio)


# connect跟disconnect 是特殊的两个事件,连接或断开时会自动调用
# 测试1：错误的：@sio.on('connect', namespace='/juran')
@sio.event(namespace='/channel_A')
def connect(sid, environ):
    print('*********')
    print('connect ', sid)
    # 测试2：没有socketio.emit()
    sio.emit('custom_messages', {'data': 'foobar'}, namespace='/channel_A')
    # 测试3：可以调用自定义函数
    print('********************************************')
    messages(sid, 'hello')


# 定义事件,有两种方式一种是用函数名另一种就是自定义的：不同于客户端
# 客户端客户端只能用@sio.on('funcName',namespace)
# 测试通过方法1：
@sio.on('messages', namespace='/channel_A')
# 测试通过方法2：
# @sio.event(namespace='/channel_A')
def messages(sid, data):
    print('**********************')
    print('messages ', data, sid)
    # 测试：不能调用已有connect(sid)
    # print('********************************************')
    # connect(sid)
    # 测试4：可以调用自定义函数
    myEmail(sid, data)


# 接收客户端发来的消息
@sio.on('myEmail', namespace='/channel_A')
def myEmail(sid, data):
    # print(sid)
    # print(data)
    print('~~~~~~~~~~~~~~~~~~~~~')
    sio.emit('custom_messages', {'data': 'foobar'}, namespace='/channel_A')


# connect跟disconnect 是特殊的两个事件,连接或断开时会自动调用
@sio.event
def disconnect(sid):
    print('disconnect ', sid)


if __name__ == '__main__':
    SERVER_ADDRESS = ('127.0.0.1', 8000)
    sock = eventlet.listen(SERVER_ADDRESS)
    eventlet.wsgi.server(sock, app)
